import random
import uuid

from flask import Flask, request, jsonify
import pymysql
from pymysql.cursors import DictCursor
import hashlib
from flask_cors import CORS
import json as JSON
from flask_mail import Mail, Message
import os

from http_demo import checklen, getText, get_answer
from util import DBCommon

app = Flask(__name__)
CORS(app)

# 数据库配置
DB_CONFIG = {
    'host': '47.113.150.140',
    'port': 8081,
    'user': 'root',
    'password': 'root',
    'database': 'guayng',
    'charset': 'utf8mb4',
    'cursorclass': DictCursor
}
# 配置邮件服务器
app.config['MAIL_SERVER'] = 'smtp.163.com'  # 替换为你的 SMTP 服务器
app.config['MAIL_PORT'] = 465  # 替换为你的 SMTP 端口
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = '15320929890@163.com'
app.config['MAIL_PASSWORD'] = 'LYQhWaSEAT3kkKvi'
app.config['MAIL_DEFAULT_SENDER'] = ('暑假大模型项目', '15320929890@163.com')

mail = Mail(app)

def sendEmail(recipient,code):
    # 创建邮件消息
    msg = Message(
        subject='大模型项目验证码',
        recipients=[recipient],
        html=f"""
        <!DOCTYPE html>
        <html lang="zh-CN">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>账户验证 - 安全验证码</title>
        </head>
        <body style="background-color: #f5f5f5; font-family: Arial, sans-serif; line-height: 1.6; color: #333; height: 100% !important; margin: 0 !important; padding: 0 !important; width: 100% !important;">
            <table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#f5f5f5">
                <tr>
                    <td align="center" style="padding: 20px 0;">
                        <table width="100%" max-width="600" border="0" cellspacing="0" cellpadding="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);">
                            <!-- 头部 -->
                            <tr>
                                <td bgcolor="#4A6CF7" style="padding: 20px; text-align: center;">
                                    <h1 style="color: white; margin: 0;">安全验证码</h1>
                                </td>
                            </tr>

                            <!-- 内容 -->
                            <tr>
                                <td style="padding: 30px;">
                                    <p style="margin: 0 0 15px 0;">尊敬的用户：</p>
                                    <p style="margin: 0 0 15px 0;">您正在进行账户验证，这是您的验证码：</p>

                                    <div style="background-color: #f8f9fa; border-radius: 4px; padding: 20px; text-align: center; margin: 20px 0;">
                                        <span style="font-size: 28px; font-weight: bold; color: #333; letter-spacing: 5px; display: block; margin: 10px 0;">{code}</span>
                                        <p style="color: #666; margin: 0;">验证码有效期为5分钟，请尽快完成验证</p>
                                    </div>

                                    <p style="margin: 0 0 15px 0;">如果您没有请求此验证码，请忽略此邮件。</p>
                                    <p style="margin: 0;">请勿向任何人分享此验证码。</p>
                                </td>
                            </tr>

                            <!-- 底部 -->
                            <tr>
                                <td style="padding: 20px; text-align: center; font-size: 12px; color: #888; border-top: 1px solid #eee;">
                                    <p style="margin: 0 0 5px 0;">© 2025 Your App. 保留所有权利。</p>
                                    <p style="margin: 0;">如果您有任何疑问，请联系我们的客服 support@yourapp.com</p>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>
            </table>
        </body>
        </html>

        """
    )

    # 发送邮件
    mail.send(msg)
    print('验证码已发送', code)

def confirmEmailCodeIfExist(cursor,recipient):
    # 查询t_email表的createTime是否存在email邮箱5分钟以内的记录
    sql = "select * from t_email where email = %s and createTime >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)"
    cursor.execute(sql, (recipient))
    res = cursor.fetchone()
    print('查询结果', res)
    return res

@app.route('/send_email', methods=['POST'])
def send_email():
    # 获取请求中的 email 参数
    data = request.get_json()
    data = JSON.loads(data.get('data'))
    print('接收到的请求',data)
    if not data or 'email' not in data:
        print('邮箱没有传入')
        return jsonify({
            'status': 'error',
            'message': '邮箱没有传入'
        }), 200

    recipient = data['email']
    type = data.get('type',False)
    print('邮箱',recipient)
    # 生成一个6位数的验证码
    code = ''.join([str(random.randint(0, 9)) for _ in range(6)])

    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                # 检查邮箱是否已存在
                sql = "select * from t_user where email = %s"
                cursor.execute(sql, (recipient))
                if cursor.fetchone():
                    print('邮箱已注册')
                    # return jsonify({'errorMsg': '邮箱已注册'}), 200
                    if type == "registerEmail": # 注册判断
                        return jsonify({
                          'status': 'error',
                          'errorMsg': '邮箱已注册'
                        }), 200
                else:
                    if type == "forgetPwd":
                        return jsonify({
                         'status': 'error',
                          'errorMsg': '邮箱未注册'
                        }), 200

                res = confirmEmailCodeIfExist(cursor,recipient)
                if res:
                    print('5分钟以内的记录已存在')
                    code = res['code']
                else:
                    sql = "insert INTO t_email (id,email,code) VALUES (null,%s,%s)"
                    cursor.execute(sql, (recipient,code))
                    conn.commit()
        sendEmail(recipient,code)
        return jsonify({
            'status': 'success',
            'message': '验证码已发送'
        }), 200

    except Exception as e:
        print('邮件发送失败',str(e))
        return jsonify({
            'status': 'error',
            'message': f'邮件发送失败: {str(e)}'
        }), 200
    # else:
    #     print('忘记密码',recipient)

def get_db_connection():
    """获取数据库连接"""
    return pymysql.connect(**DB_CONFIG)


# 创建用户
@app.route('/api/users', methods=['POST'])
def create_user():
    data = request.get_json()
    data = JSON.loads(data.get('data'))
    print(f'接收到的请求: {data}')
    name = data.get('name')
    email = data.get('email')
    pwd = data.get('pwd')
    pwdConfirm = data.get('pwdConfirm')
    code = data.get('code')
    # 校验pwd和pwdConfirm是否一致
    if pwd != pwdConfirm:
        return jsonify({'errorMsg': '两次输入的密码不一致'}), 200

    if not name or not email or not pwd or not pwdConfirm or not code:
        return jsonify({'errorMsg': '缺少必要参数'}), 200

    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                # 检查邮箱是否已存在
                sql = "SELECT * FROM t_user WHERE email = %s"
                cursor.execute(sql, (email,))
                if cursor.fetchone():
                    return jsonify({'errorMsg': '邮箱已被注册'}), 200
                # 检查验证码是否存在，且在5分钟以内
                sql = "SELECT * FROM t_email WHERE email = %s AND code = %s AND createTime >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)"
                cursor.execute(sql, (email, code))
                if not cursor.fetchone():
                    return jsonify({'errorMsg': '验证码无效或已过期'}), 200

                # 密码加密存储（使用SHA-256）
                pwd_hash = hashlib.sha256(pwd.encode('utf-8')).hexdigest()

                sql = "INSERT INTO t_user (name, email, pwd) VALUES (%s, %s, %s)"
                cursor.execute(sql, (name, email, pwd_hash))
                conn.commit()
                user_id = cursor.lastrowid
        return jsonify({'message': '用户创建成功', 'id': user_id}), 200
    except pymysql.Error as e:
        return jsonify({'errorMsg': f'用户创建失败: {str(e)}'}), 200
# 忘记密码
@app.route('/', methods=['GET'])
def hello():
    return 'Hello, World!'
@app.route('/api/users', methods=['PUT'])
def forgetPwd():
    data = request.get_json()
    data = JSON.loads(data.get('data'))
    print(f'接收到的请求: {data}')
    email = data.get('email')
    code = data.get('code')
    pwd = data.get('pwd')
    pwdConfirm = data.get('pwdConfirm')
    # 校验pwd和pwdConfirm是否一致
    if pwd != pwdConfirm:
        return jsonify({'errorMsg': '两次输入的密码不一致'}), 200

    if not email or not pwd or not pwdConfirm or not code:
        return jsonify({'errorMsg': '缺少必要参数'}), 200

    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                # 检查邮箱是否已存在
                sql = "SELECT * FROM t_user WHERE email = %s"
                cursor.execute(sql, (email,))
                if not cursor.fetchone():
                    return jsonify({'errorMsg': '邮箱未注册'}), 200
                # 检查验证码是否存在，且在5分钟以内
                sql = "SELECT * FROM t_email WHERE email = %s AND code = %s AND createTime >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)"
                cursor.execute(sql, (email, code))
                if not cursor.fetchone():
                    return jsonify({'errorMsg': '验证码无效或已过期'}), 200

                # 密码加密存储（使用SHA-256）
                pwd_hash = hashlib.sha256(pwd.encode('utf-8')).hexdigest()

                sql = "update t_user set pwd = %s where email = %s"
                cursor.execute(sql, (pwd_hash, email, ))
                conn.commit()
        return jsonify({'message': '密码已重置'}), 200
    except pymysql.Error as e:
        return jsonify({'errorMsg': f'密码重置失败: {str(e)}'}), 200


# 用户登录接口
@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    print(f'接收到的请求: {data}')
    data1 = data.get('data')
    print(f'接收到的请求data1: {data1}')
    # 判断data1是否是json格式，如果不是就格式化一下
    if not isinstance(data1, dict):
        data1 = JSON.loads(data1)
    email = data1.get('email')
    pwd = data1.get('pwd')
    print(f'邮箱: {email}, 密码: {pwd}')

    if not email or not pwd:
        print('缺少邮箱或密码')
        return jsonify({'errorMsg': '缺少邮箱或密码'}), 200

    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                # 计算密码哈希值
                pwd_hash = hashlib.sha256(pwd.encode('utf-8')).hexdigest()
                print('开始查询数据库',pwd_hash)

                sql = "SELECT * FROM t_user WHERE email = %s AND pwd = %s"
                cursor.execute(sql, (email, pwd_hash))
                user = cursor.fetchone()

        if user:
            # 登录成功，返回用户信息（不包含密码）
            user.pop('pwd')
            print('登录成功',user)
            # 存一个session到数据库
            with get_db_connection() as conn:
                with conn.cursor() as cursor:
                    sql = "insert into t_session (userId) values (%s)"
                    cursor.execute(sql, (user['id'],))
                    conn.commit()
            return jsonify({
                'message': '登录成功',
                'user': user
            }), 200
        else:
            print('邮箱或密码错误')
            return jsonify({'errorMsg': '邮箱或密码错误'}), 200

    except pymysql.Error as e:
        print(f'数据库错误: {str(e)}')
        return jsonify({'errorMsg': f'数据库错误: {str(e)}'}), 200


# 获取用户列表
@app.route('/api/users', methods=['GET'])
def get_users():
    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                sql = "SELECT id, name, email FROM t_user"  # 不返回密码
                cursor.execute(sql)
                users = cursor.fetchall()
        return jsonify(users), 200
    except pymysql.Error as e:
        return jsonify({'errorMsg': f'数据库错误: {str(e)}'}), 200


# 获取单个用户
@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                sql = "SELECT id, name, email FROM t_user WHERE id = %s"  # 不返回密码
                cursor.execute(sql, (user_id,))
                user = cursor.fetchone()
        if not user:
            return jsonify({'errorMsg': '用户不存在'}), 200
        return jsonify(user), 200
    except pymysql.Error as e:
        return jsonify({'errorMsg': f'数据库错误: {str(e)}'}), 200


# 更新用户
@app.route('/api/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    data = request.get_json()
    name = data.get('name')
    email = data.get('email')
    pwd = data.get('pwd')

    if not any([name, email, pwd]):
        return jsonify({'errorMsg': '至少需要提供一个更新字段'}), 200

    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                # 检查用户是否存在
                sql = "SELECT * FROM t_user WHERE id = %s"
                cursor.execute(sql, (user_id,))
                user = cursor.fetchone()
                if not user:
                    return jsonify({'errorMsg': '用户不存在'}), 200

                # 构建更新语句
                set_clause = []
                params = []
                if name:
                    set_clause.append("name = %s")
                    params.append(name)
                if email:
                    # 检查新邮箱是否已被使用（除当前用户外）
                    sql = "SELECT * FROM t_user WHERE email = %s AND id != %s"
                    cursor.execute(sql, (email, user_id))
                    if cursor.fetchone():
                        return jsonify({'errorMsg': '该邮箱已被其他用户使用'}), 200
                    set_clause.append("email = %s")
                    params.append(email)
                if pwd:
                    # 密码加密更新
                    pwd_hash = hashlib.sha256(pwd.encode('utf-8')).hexdigest()
                    set_clause.append("pwd = %s")
                    params.append(pwd_hash)
                params.append(user_id)

                sql = f"UPDATE t_user SET {', '.join(set_clause)} WHERE id = %s"
                cursor.execute(sql, params)
                conn.commit()
        return jsonify({'message': '用户更新成功'}), 200
    except pymysql.Error as e:
        return jsonify({'errorMsg': f'数据库错误: {str(e)}'}), 200


# 删除用户
@app.route('/api/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
    try:
        with get_db_connection() as conn:
            with conn.cursor() as cursor:
                # 检查用户是否存在
                sql = "SELECT * FROM t_user WHERE id = %s"
                cursor.execute(sql, (user_id,))
                user = cursor.fetchone()
                if not user:
                    return jsonify({'errorMsg': '用户不存在'}), 200

                sql = "DELETE FROM t_user WHERE id = %s"
                cursor.execute(sql, (user_id,))
                conn.commit()
        return jsonify({'message': '用户删除成功'}), 200
    except pymysql.Error as e:
        return jsonify({'errorMsg': f'数据库错误: {str(e)}'}), 200
def saveChat(senderId,role,content,conventionId,title=''):
    db = DBCommon(
        host=DB_CONFIG['host'],
        user=DB_CONFIG['user'],
        password=DB_CONFIG['password'],
        database=DB_CONFIG['database'],
        port=DB_CONFIG['port'],
    )
    insert_data = {
        "title": title,
        "senderId": senderId,
        "role": role,
        "conventionId": conventionId,
        "content": content
    }
    db.insert('t_chat', insert_data)
def getChat(conventionId):
    db = DBCommon(
        host=DB_CONFIG['host'],
        user=DB_CONFIG['user'],
        password=DB_CONFIG['password'],
        database=DB_CONFIG['database'],
        port=DB_CONFIG['port'],
    )
    result = db.select_all('t_chat', condition='conventionId = %s', params=(conventionId,))
    for item in result:
        if 'createTime' in item and item['createTime']:
            item['createTime'] = item['createTime'].strftime('%Y-%m-%d %H:%M:%S')
    return result
# 添加一个大模型会话接口，传入参数会话id默认为空，如果不为空就查询历史记录，为空就新建一个会话，再传一个参数content，content是用户输入的内容，返回一个json，包含id和content，id是会话id，content是模型返回的内容
@app.route('/api/chat', methods=['POST'])
def apiChat():
    try:
        data = request.get_json()
        print(f'接收到的请求: {data}')
        content = data.get('content')
        user = data.get('user')
        conventionId = data.get('conventionId')
        print(f'接收到的请求data1: {content}')
        print(f'user: {user}')
        print(f'conventionId: {conventionId}')
        user = JSON.loads(user)
        title = ""
        if not conventionId:
            title = content
            conventionId = uuid.uuid4()

        saveChat(user['id'],"user",content,conventionId,title)

        # 获取历史会话记录


        chatHistory = getChat(conventionId)
        # chatHistory = []
        print(f'历史会话记录: {chatHistory}')
        # Input = input("\n" + "我:")
        question = checklen(getText(chatHistory,"user", content))
        # 开始输出模型内容
        print("星火:", end="")
        res = getText(chatHistory,"assistant", get_answer(question))
        saveChat(user['id'],"assistant",res[1]['content'],conventionId)
        return jsonify({
            'content': res,
            'conventionId': conventionId
        }), 200
    except Exception as e:
        print(f'错误: {str(e)}')
        return jsonify({'errorMsg': f'错误: {str(e)}'}), 200


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9000, debug=True)